home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / mail / db.1.85.tar.gz / db.1.85.tar / db.1.85 / recno / rec_open.c < prev    next >
C/C++ Source or Header  |  1994-09-01  |  7KB  |  242 lines

  1. /*-
  2.  * Copyright (c) 1990, 1993, 1994
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Mike Olson.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #if defined(LIBC_SCCS) && !defined(lint)
  38. static char sccsid[] = "@(#)rec_open.c    8.10 (Berkeley) 9/1/94";
  39. #endif /* LIBC_SCCS and not lint */
  40.  
  41. #include <sys/types.h>
  42. #include <sys/mman.h>
  43. #include <sys/stat.h>
  44.  
  45. #include <errno.h>
  46. #include <fcntl.h>
  47. #include <limits.h>
  48. #include <stddef.h>
  49. #include <stdio.h>
  50. #include <unistd.h>
  51.  
  52. #include <db.h>
  53. #include "recno.h"
  54.  
  55. DB *
  56. __rec_open(fname, flags, mode, openinfo, dflags)
  57.     const char *fname;
  58.     int flags, mode, dflags;
  59.     const RECNOINFO *openinfo;
  60. {
  61.     BTREE *t;
  62.     BTREEINFO btopeninfo;
  63.     DB *dbp;
  64.     PAGE *h;
  65.     struct stat sb;
  66.     int rfd, sverrno;
  67.  
  68.     /* Open the user's file -- if this fails, we're done. */
  69.     if (fname != NULL && (rfd = open(fname, flags, mode)) < 0)
  70.         return (NULL);
  71.  
  72.     /* Create a btree in memory (backed by disk). */
  73.     dbp = NULL;
  74.     if (openinfo) {
  75.         if (openinfo->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT))
  76.             goto einval;
  77.         btopeninfo.flags = 0;
  78.         btopeninfo.cachesize = openinfo->cachesize;
  79.         btopeninfo.maxkeypage = 0;
  80.         btopeninfo.minkeypage = 0;
  81.         btopeninfo.psize = openinfo->psize;
  82.         btopeninfo.compare = NULL;
  83.         btopeninfo.prefix = NULL;
  84.         btopeninfo.lorder = openinfo->lorder;
  85.         dbp = __bt_open(openinfo->bfname,
  86.             O_RDWR, S_IRUSR | S_IWUSR, &btopeninfo, dflags);
  87.     } else
  88.         dbp = __bt_open(NULL, O_RDWR, S_IRUSR | S_IWUSR, NULL, dflags);
  89.     if (dbp == NULL)
  90.         goto err;
  91.  
  92.     /*
  93.      * Some fields in the tree structure are recno specific.  Fill them
  94.      * in and make the btree structure look like a recno structure.  We
  95.      * don't change the bt_ovflsize value, it's close enough and slightly
  96.      * bigger.
  97.      */
  98.     t = dbp->internal;
  99.     if (openinfo) {
  100.         if (openinfo->flags & R_FIXEDLEN) {
  101.             F_SET(t, R_FIXLEN);
  102.             t->bt_reclen = openinfo->reclen;
  103.             if (t->bt_reclen == 0)
  104.                 goto einval;
  105.         }
  106.         t->bt_bval = openinfo->bval;
  107.     } else
  108.         t->bt_bval = '\n';
  109.  
  110.     F_SET(t, R_RECNO);
  111.     if (fname == NULL)
  112.         F_SET(t, R_EOF | R_INMEM);
  113.     else
  114.         t->bt_rfd = rfd;
  115.  
  116.     if (fname != NULL) {
  117.         /*
  118.          * In 4.4BSD, stat(2) returns true for ISSOCK on pipes.
  119.          * Unfortunately, that's not portable, so we use lseek
  120.          * and check the errno values.
  121.          */
  122.         errno = 0;
  123.         if (lseek(rfd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE) {
  124.             switch (flags & O_ACCMODE) {
  125.             case O_RDONLY:
  126.                 F_SET(t, R_RDONLY);
  127.                 break;
  128.             default:
  129.                 goto einval;
  130.             }
  131. slow:            if ((t->bt_rfp = fdopen(rfd, "r")) == NULL)
  132.                 goto err;
  133.             F_SET(t, R_CLOSEFP);
  134.             t->bt_irec =
  135.                 F_ISSET(t, R_FIXLEN) ? __rec_fpipe : __rec_vpipe;
  136.         } else {
  137.             switch (flags & O_ACCMODE) {
  138.             case O_RDONLY:
  139.                 F_SET(t, R_RDONLY);
  140.                 break;
  141.             case O_RDWR:
  142.                 break;
  143.             default:
  144.                 goto einval;
  145.             }
  146.  
  147.             if (fstat(rfd, &sb))
  148.                 goto err;
  149.             /*
  150.              * Kluge -- we'd like to test to see if the file is too
  151.              * big to mmap.  Since, we don't know what size or type
  152.              * off_t's or size_t's are, what the largest unsigned
  153.              * integral type is, or what random insanity the local
  154.              * C compiler will perpetrate, doing the comparison in
  155.              * a portable way is flatly impossible.  Hope that mmap
  156.              * fails if the file is too large.
  157.              */
  158.             if (sb.st_size == 0)
  159.                 F_SET(t, R_EOF);
  160.             else {
  161. #ifdef MMAP_NOT_AVAILABLE
  162.                 /*
  163.                  * XXX
  164.                  * Mmap doesn't work correctly on many current
  165.                  * systems.  In particular, it can fail subtly,
  166.                  * with cache coherency problems.  Don't use it
  167.                  * for now.
  168.                  */
  169.                 t->bt_msize = sb.st_size;
  170.                 if ((t->bt_smap = mmap(NULL, t->bt_msize,
  171.                     PROT_READ, MAP_PRIVATE, rfd,
  172.                     (off_t)0)) == (caddr_t)-1)
  173.                     goto slow;
  174.                 t->bt_cmap = t->bt_smap;
  175.                 t->bt_emap = t->bt_smap + sb.st_size;
  176.                 t->bt_irec = F_ISSET(t, R_FIXLEN) ?
  177.                     __rec_fmap : __rec_vmap;
  178.                 F_SET(t, R_MEMMAPPED);
  179. #else
  180.                 goto slow;
  181. #endif
  182.             }
  183.         }
  184.     }
  185.  
  186.     /* Use the recno routines. */
  187.     dbp->close = __rec_close;
  188.     dbp->del = __rec_delete;
  189.     dbp->fd = __rec_fd;
  190.     dbp->get = __rec_get;
  191.     dbp->put = __rec_put;
  192.     dbp->seq = __rec_seq;
  193.     dbp->sync = __rec_sync;
  194.  
  195.     /* If the root page was created, reset the flags. */
  196.     if ((h = mpool_get(t->bt_mp, P_ROOT, 0)) == NULL)
  197.         goto err;
  198.     if ((h->flags & P_TYPE) == P_BLEAF) {
  199.         F_CLR(h, P_TYPE);
  200.         F_SET(h, P_RLEAF);
  201.         mpool_put(t->bt_mp, h, MPOOL_DIRTY);
  202.     } else
  203.         mpool_put(t->bt_mp, h, 0);
  204.  
  205.     if (openinfo && openinfo->flags & R_SNAPSHOT &&
  206.         !F_ISSET(t, R_EOF | R_INMEM) &&
  207.         t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
  208.                 goto err;
  209.     return (dbp);
  210.  
  211. einval:    errno = EINVAL;
  212. err:    sverrno = errno;
  213.     if (dbp != NULL)
  214.         (void)__bt_close(dbp);
  215.     if (fname != NULL)
  216.         (void)close(rfd);
  217.     errno = sverrno;
  218.     return (NULL);
  219. }
  220.  
  221. int
  222. __rec_fd(dbp)
  223.     const DB *dbp;
  224. {
  225.     BTREE *t;
  226.  
  227.     t = dbp->internal;
  228.  
  229.     /* Toss any page pinned across calls. */
  230.     if (t->bt_pinned != NULL) {
  231.         mpool_put(t->bt_mp, t->bt_pinned, 0);
  232.         t->bt_pinned = NULL;
  233.     }
  234.  
  235.     /* In-memory database can't have a file descriptor. */
  236.     if (F_ISSET(t, R_INMEM)) {
  237.         errno = ENOENT;
  238.         return (-1);
  239.     }
  240.     return (t->bt_rfd);
  241. }
  242.